﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TemplateEngineWithChart.Docx.FullExample
{
    #region DataRow的扩展方法
    /// <summary>
    /// DataRow的扩展方法
    /// </summary>
    public static class DataRowExtensionMethods
    {
        /// <summary>
        /// 把DataRow中的某一列值转换为十进制数
        /// </summary>
        /// <param name="row">数据行</param>
        /// <param name="columnName">列名</param>
        /// <returns></returns>
        public static decimal DataRowToDecimal(this DataRow row, string columnName)
        {
            if (!row.Table.Columns.Contains(columnName))
            {
                return 0M;
            }

            if (row.IsNull(columnName))
            {
                return 0M;
            }

            decimal result;
            if (decimal.TryParse(row[columnName].ToString(), out result))
            {
                return result;
            }
            else
            {
                return 0M;
            }
        }

        /// <summary>
        /// 把DataRow中的某一列值转换为十进制数
        /// </summary>
        /// <param name="row">数据行</param>
        /// <param name="columnName">列名</param>
        /// <returns>可能为空</returns>
        public static decimal? DataRowToDecimalNull(this DataRow row, string columnName)
        {
            if (!row.Table.Columns.Contains(columnName))
            {
                return null;
            }

            if (row.IsNull(columnName))
            {
                return null;
            }

            decimal result;
            if (decimal.TryParse(row[columnName].ToString(), out result))
            {
                return result;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 把DataRow中的某一列值转换为字符串
        /// </summary>
        /// <param name="row">数据行</param>
        /// <param name="columnName">列名</param>
        /// <returns></returns>
        public static string DataRowToString(this DataRow row, string columnName)
        {
            if (!row.Table.Columns.Contains(columnName))
            {
                return string.Empty;
            }

            if (row.IsNull(columnName))
            {
                return string.Empty;
            }

            // 解决字符串中有换行符且换行符是\r或者\n的问题：
            // 1.先把字符串中的\r\n转换为"{{空格}}"
            // 2.再把字符串中的\r和\n转换为"{{空格}}"
            // 3.把"{{空格}}"转换为\r\n
            string value = row[columnName].ToString();
            string placeholder = "{{空格}}";
            if (value.Contains("\r\n"))
            {
                value = value.Replace("\r\n", placeholder);
            }

            if (value.Contains("\r"))
            {
                value = value.Replace("\r", placeholder);
            }

            if (value.Contains("\n"))
            {
                value = value.Replace("\n", placeholder);
            }

            if (value.Contains(placeholder))
            {
                value = value.Replace(placeholder, "\r\n");
            }

            return value;
        }

        /// <summary>
        /// 把DataRow中的某一列值转换为时间
        /// </summary>
        /// <param name="row">数据行</param>
        /// <param name="columnName">列名</param>
        /// <returns></returns>
        public static DateTime DataRowToDateTime(this DataRow row, string columnName)
        {
            if (!row.Table.Columns.Contains(columnName))
            {
                return DateTime.Now;
            }

            if (row.IsNull(columnName))
            {
                return DateTime.Now;
            }

            DateTime result;
            if (DateTime.TryParse(row[columnName].ToString(), out result))
            {
                return result;
            }
            else
            {
                return DateTime.Now;
            }
        }

        /// <summary>
        /// 把DataRow中的某一列值转换为时间
        /// </summary>
        /// <param name="row">数据行</param>
        /// <param name="columnName">列名</param>
        /// <returns></returns>
        public static DateTime? DataRowToDateTimeNull(this DataRow row, string columnName)
        {
            if (!row.Table.Columns.Contains(columnName))
            {
                return null;
            }

            if (row.IsNull(columnName))
            {
                return null;
            }

            DateTime result;
            if (DateTime.TryParse(row[columnName].ToString(), out result))
            {
                return result;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 把DataRow中的某一列值转换为日期
        /// </summary>
        /// <param name="row">数据行</param>
        /// <param name="columnName">列名</param>
        /// <returns></returns>
        public static DateTime DataRowToDate(this DataRow row, string columnName)
        {
            if (!row.Table.Columns.Contains(columnName))
            {
                return DateTime.Now.Date;
            }

            if (row.IsNull(columnName))
            {
                return DateTime.Now.Date;
            }

            DateTime result;
            if (DateTime.TryParse(row[columnName].ToString(), out result))
            {
                return result.Date;
            }
            else
            {
                return DateTime.Now.Date;
            }
        }

        /// <summary>
        /// 把DataRow中的某一列值转换为日期
        /// </summary>
        /// <param name="row">数据行</param>
        /// <param name="columnName">列名</param>
        /// <returns></returns>
        public static DateTime? DataRowToDateNull(this DataRow row, string columnName)
        {
            if (!row.Table.Columns.Contains(columnName))
            {
                return null;
            }

            if (row.IsNull(columnName))
            {
                return null;
            }

            DateTime result;
            if (DateTime.TryParse(row[columnName].ToString(), out result))
            {
                return result.Date;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 把DataRow转换为数据字典
        /// </summary>
        /// <param name="row"></param>
        /// <returns></returns>
        public static Dictionary<string, object> DataRowToDictionary(this DataRow row)
        {
            if (row.Table.Columns.Count > 0)
            {
                Dictionary<string, object> dic = new Dictionary<string, object>();
                for (int i = 0; i < row.Table.Columns.Count; i++)
                {
                    var columnName = row.Table.Columns[i].ColumnName;
                    dic.Add(columnName, row[columnName]);
                }

                return dic;
            }

            return null;
        }

        /// <summary>
        /// 把DataRow中的某一列值转换为布尔类型
        /// </summary>
        /// <param name="row">数据行</param>
        /// <param name="columnName">列名</param>
        /// <returns></returns>
        public static bool DataRowToBool(this DataRow row, string columnName)
        {
            if (!row.Table.Columns.Contains(columnName))
            {
                return false;
            }

            if (row.IsNull(columnName))
            {
                return false;
            }

            bool result;
            if (bool.TryParse(row[columnName].ToString(), out result))
            {
                return result;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 把DataRow中的某一列值转换为布尔类型
        /// </summary>
        /// <param name="row">数据行</param>
        /// <param name="columnName">列名</param>
        /// <returns></returns>
        public static bool? DataRowToBoolNull(this DataRow row, string columnName)
        {
            if (!row.Table.Columns.Contains(columnName))
            {
                return null;
            }

            if (row.IsNull(columnName))
            {
                return null;
            }

            bool result;
            if (bool.TryParse(row[columnName].ToString(), out result))
            {
                return result;
            }
            else
            {
                return null;
            }
        }

        public static List<FieldContent> DataRowToFields(this DataRow row, string tableName)
        {
            List<FieldContent> rows = new List<FieldContent>();
            for (int j = 0; j < row.Table.Columns.Count; j++)
            {
                DataColumn dc = row.Table.Columns[j];
                rows.Add(new FieldContent($"{tableName}.{dc.ColumnName}", row.DataRowToString(dc.ColumnName)));
            }

            return rows;
        }
    }
    #endregion

    public static class DataTableExtensions
    {
        public static TableContent DataTableToTableContent(this DataTable dt, string tableName = null)
        {
            TableContent table = TableContent.Create(tableName);
            if (dt != null && dt.Rows.Count > 0)
            {
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    List<FieldContent> rows = new List<FieldContent>();
                    for (int j = 0; j < dt.Columns.Count; j++)
                    {
                        DataColumn dc = dt.Columns[j];
                        rows.Add(new FieldContent($"{tableName}.{dc.ColumnName}", dt.Rows[i][dc.ColumnName].ToString()));
                    }

                    table.AddRow(rows.ToArray());
                }
            }
            else
            {
                table.Hide();
            }

            return table;
        }

        public static ListContent DataTableToListContent(this DataTable dt, string columnName)
        {
            ListContent listContent = new ListContent(dt.TableName);
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                listContent.AddItem(new FieldContent($"{dt.TableName}.{columnName}", dt.Rows[i].Field<string>(columnName)));
            }

            return listContent;
        }
    }
}
